/**
 * @description 股票数据服务
 */
const axios = require('axios')

class StockService {
  constructor() {
    this.baseUrl = 'http://push2his.eastmoney.com/api/qt/stock/kline/get'
    this.listUrl = 'http://push2.eastmoney.com/api/qt/clist/get'
    // 设置请求配置
    this.axiosConfig = {
      timeout: 20000,  // 超时时间设置为20秒
      headers: {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
      }
    }
  }

  /**
   * @description 获取所有股票列表
   */
  async getStockList() {
    try {
      // 分页获取所有数据
      const pageSize = 200
      let allStocks = []
      const totalPages = 28
      
      // 创建所有页面的请求数组
      const pageRequests = Array.from({ length: totalPages }, (_, i) => {
        const params = {
          pn: i + 1, // 页码
          pz: pageSize, // 每页数量
          po: 0, // 不排序
          np: 1,
          ut: 'bd1d9ddb04089700cf9c27f6f7426281',
          fltt: 2,
          invt: 2,
          fid: 'f62',
          fs: 'm:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23', // 沪深A股
          fields: 'f12,f14,f2,f3,f9,f8,f10,f1,f152'
        }
        return axios.get(this.listUrl, { 
          ...this.axiosConfig,
          params 
        })
      })

      // 并发请求所有页面数据
      const responses = await Promise.all(pageRequests)
      
      // 处理每页数据
      for (const response of responses) {
        if (!response.data.data || !response.data.data.diff) continue
        
        const currentPageStocks = await Promise.all(response.data.data.diff.map(async item => {
          try {
            const params = {
              secid: `${item.f12.startsWith('6') ? 1 : 0}.${item.f12}`,
              ut: 'fa5fd1943c7b386f172d6893dbfba10b',
              fields1: 'f1,f2,f3,f4,f5,f6',
              fields2: 'f51,f52,f53,f54,f55,f56,f57,f58',
              klt: 101,
              fqt: 1,
              end: 20500101,
              lmt: 5
            }
            
            const response = await axios.get(this.baseUrl, {
              ...this.axiosConfig,
              params
            })

            if (response.data.data && response.data.data.klines) {
              const klines = response.data.data.klines.reverse()
              const history = klines.map(line => {
                const [date, open, close, high, low, volume] = line.split(',')
                return {
                  date,
                  price: parseFloat(close),
                  volume: parseFloat(volume)
                }
              })
              const historyPrices = history.map(h => h.price)
              
              // 计算3日和5日涨幅
              const threeDayChange = historyPrices.length >= 3 ? 
                ((historyPrices[0] - historyPrices[2]) / historyPrices[2] * 100).toFixed(2) : 0
              const fiveDayChange = historyPrices.length >= 5 ? 
                ((historyPrices[0] - historyPrices[4]) / historyPrices[4] * 100).toFixed(2) : 0
              
              // 计算连板天数
              const limitUpDays = this.calculateLimitUpDays(history, item.f152, item.f12)
              
              return {
                code: item.f12,
                name: item.f14,
                price: parseFloat(item.f2) || 0,
                changePercent: parseFloat(item.f3) || 0,
                threeDayChange: parseFloat(threeDayChange),
                fiveDayChange: parseFloat(fiveDayChange),
                turnoverRate: item.f8,
                volumeRatio: item.f10,
                pe: item.f9,
                limitUpDays
              }
            }
            return []
          } catch (error) {
            console.error(`获取${item.f12}历史数据失败: ${error.message}`)
            if (error.code === 'ETIMEDOUT') {
              // 如果是超时错误，等待1秒后重试
              await new Promise(resolve => setTimeout(resolve, 1000))
              return this.getStockHistory(item.f12)
            }
            return []
          }
        }))

        allStocks = allStocks.concat(currentPageStocks)
        // 为了避免请求过于频繁，增加延时
        await new Promise(resolve => setTimeout(resolve, 200))
      }
      
      // 过滤掉无效数据
      const validStocks = allStocks.filter(stock => 
        !isNaN(stock.changePercent) && 
        stock.price > 0 && 
        stock.name && 
        stock.code
      )
      
      return validStocks
    } catch (error) {
      console.error('获取股票列表失败:', error)
      return []
    }
  }

  /**
   * @description 获取股票历史数据
   */
  async getStockHistory(code) {
    try {
      const params = {
        secid: `${code.startsWith('6') ? 1 : 0}.${code}`,
        ut: 'fa5fd1943c7b386f172d6893dbfba10b',
        fields1: 'f1,f2,f3,f4,f5,f6',
        fields2: 'f51,f52,f53,f54,f55,f56,f57,f58',
        klt: 101, // 日K
        fqt: 1,
        end: 20500101,
        lmt: 5 // 最近5天数据
      }
      
      const response = await axios.get(this.baseUrl, { params })
      if (response.data.data && response.data.data.klines) {
        const klines = response.data.data.klines.reverse() // 倒序，最新的在前
        return klines.map(line => {
          const [date, open, close, high, low, volume] = line.split(',')
          return {
            date,
            price: parseFloat(close),
            volume: parseFloat(volume)
          }
        })
      }
      
      return []
    } catch (error) {
      console.error('获取历史数据失败:', error)
      return []
    }
  }

  /**
   * @description 计算连板天数
   * @param {Array} history 历史数据
   * @param {number} limitUpPrice 涨停价
   * @param {string} code 股票代码
   * @returns {number} 连板天数
   */
  calculateLimitUpDays(history, limitUpPrice, code) {
    let days = 0
    // 确保有历史数据
    if (!history || history.length === 0) return days
    
    // 获取最新一天的涨停价
    const latestLimitUpPrice = limitUpPrice
    if (!latestLimitUpPrice) return days
    
    // 判断股票所属板块
    const isSTAR = code.startsWith('688')    // 科创板
    const isGEM = code.startsWith('300') || code.startsWith('301')  // 创业板
    const limitUpPercent = isSTAR || isGEM ? 20 : 10  // 科创板和创业板20%，主板10%
    
    for (let i = 0; i < history.length; i++) {
      // 计算当日涨幅
      const prevPrice = i < history.length - 1 ? history[i + 1].price : history[i].price
      const changePercent = ((history[i].price - prevPrice) / prevPrice) * 100
      
      // 判断是否涨停：
      // 1. 收盘价接近涨停价（考虑误差范围）
      // 2. 涨幅接近涨停幅度（考虑误差范围）
      const priceNearLimit = Math.abs(history[i].price - latestLimitUpPrice) < 0.02
      const isNearLimit = changePercent >= (limitUpPercent - 0.5)  // 允许0.5%的误差
      
      const isLimitUp = priceNearLimit || isNearLimit
      
      if (isLimitUp) {
        days++
      } else {
        break // 一旦不是涨停就结束计算
      }
    }
    return days
  }
}

module.exports = { StockService } 